#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <time.h>
#include <sys/types.h>
#include <signal.h>

#define READ_TIMEOUT 10 //sec
#define MAXLINE 512 * 1024

#define FILE_MODE   (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) 

#if defined(FILE_PRINT) && (FILE_PRINT)
#else
  #define printf file_printf
#endif


void file_printf(const char *fmt, ...){
   int save_errno ,n;
   FILE *fp;
   char buff[1024*2];
   save_errno = errno;

   time_t  st = time(NULL);
   struct tm *tm = localtime(&st);
   sprintf(buff,"[%02d-%02d %02d:%02d:%02d] ",tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);
   n = strlen(buff);

   va_list ap;
   va_start(ap,fmt); 
   #ifdef HAVE_VSNPRINTF 
   vsnprintf(buff+n,sizeof(buf)-n,fmt,ap);
   #else
   vsprintf(buff+n,fmt,ap);
   #endif
   va_end(ap);
  
   if(save_errno){
     n = strlen(buff);
     snprintf(buff+n,sizeof(buff)-n,", %d:%s",errno,strerror(save_errno));
   }
   strcat(buff,"\n");


   char filename[1024];
   sprintf(filename,"./fifo2stdout.%04d-%02d-%02d.log",tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday);
   fp = fopen(filename,"ab"); 
   if(fp == NULL){
     strcat(buff," , cant fopen log");
     fflush(stdout); 
     fputs(buff,stderr);
     fflush(stderr);
     return;
   }

   fputs(buff,fp);
   fflush(fp);
   fclose(fp);
}

/*void * check_timeout(void *arg)
{
   while(){
   }
   return arg; 
}*/


void alarm_proc(int signal)
{
   printf("received signal:%d and exited",signal);
   exit(1);
}

int main(int argc ,char *argv[])
{
    int in;
    char buff[MAXLINE]={'\0'};
    char outbuff[256*1024] ={'\0'};
    struct sigaction sa;

    if(argc < 2){
      printf("Usage: fifo2stdout <fifo_file>\n");
      exit(1);
    }

    if((mkfifo(argv[1],FILE_MODE)) ==-1 && errno != EEXIST) {
      printf("mkfifo %s error",argv[1]); 
      exit(1);
    }

    setbuffer(stdout,outbuff,256*1024);
   
    sa.sa_handler = alarm_proc;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags   = 0;
    sigaddset(&sa.sa_mask,SIGALRM);
    sigaction(SIGALRM,&sa,(struct sigaction*)0); 
    
    //signal(SIGALRM,alarm_proc);

    if(errno == EEXIST) errno = 0;
    printf("mkfifo %s successed",argv[1]);

    in = open(argv[1],O_RDONLY,0);
    if(in < 0){
      printf("open %s error",argv[1]);
      exit(1);
    }
    printf("open %s successed fd:%d",argv[1],in);
    int len;
    while(1){
       //alarm(READ_TIMEOUT);
       len = read(in,buff,MAXLINE);
       //alarm(0);
       printf("read %s len:%d",argv[1],len);
       if(len <= 0 ){
          break;
       }
       int slen = len;
       char *tmp = buff;
       int sslen = -1;
       while(slen > 0){
          sslen = write(STDOUT_FILENO,tmp,slen);
          printf("write %s len:%d",argv[1],sslen);
          if(sslen <= 0){
            break;
          }
          slen -= sslen;
          tmp += sslen;
       }
       if( sslen < 0 ){
          printf("write error:%s\n",strerror(errno)); 
          close(in);
          exit(1);
       }
    }

    if(len < 0){
       printf("read error:%s\n",strerror(errno)); 
       close(in);
       exit(1);
    }

    printf("live %s end",argv[1]);
    unlink(argv[1]);
    close(in);
    return 0;
}
